/* Copyright 2010 by Matt Van Der Westhuizen */

package org.chaoticengine.ast.view;

import org.chaoticengine.ast.model.Location;
import org.chaoticengine.ast.model.WorldMap;
import org.chaoticengine.ast.pattern.ViewController;
import org.chaoticengine.cgll.camera.Camera;
import org.newdawn.slick.Color;
import org.newdawn.slick.GameContainer;
import org.newdawn.slick.Graphics;
import org.newdawn.slick.Image;
import org.newdawn.slick.Input;
import org.newdawn.slick.SlickException;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Vector2f;
import org.newdawn.slick.state.StateBasedGame;

/**
 *
 * @author Matt Van Der Westhuizen <mattpwest@gmail.com>
 */
public class MiniMapView extends ViewController<WorldMap> {
    protected WorldMap map = null;
    protected Image mini = null;
    protected int mapW = 0;
    protected int mapH = 0;
    protected boolean lmb = false; // Is LMB down?
    
    /** Reference to the camera of the map view. */
    protected Camera cam = null;

    @Override
    public WorldMap getModel() {
        return(map);
    }

    public Camera getCamera() {
        return(cam);
    }

    public void setCamera(Camera camera) {
        this.cam = camera;
    }

    @Override
    public void keyPressed(int key, char c) {}

    @Override
    public void keyReleased(int key, char c) {}

    @Override
    public void onMouseClick(int x, int y, int button) {
        if ((bounds.contains(x, y)) && (button == Input.MOUSE_LEFT_BUTTON)) {
            lmb = true;

            viewPosition(x, y);
        }
    }

    @Override
    public void onMouseEnter() {
    }

    @Override
    public void onMouseExit() {
    }

    @Override
    public void onMouseMove(int oldx, int oldy, int newx, int newy) {
        if ((lmb) && (bounds.contains(newx, newy))) {
            viewPosition(newx, newy);
        }
    }

    @Override
    public void onMouseRelease(int x, int y, int button) {
        if (button == Input.MOUSE_LEFT_BUTTON) {
            lmb = false;
        }
    }

    @Override
    public void onMouseWheelDown() {}

    @Override
    public void onMouseWheelUp() {}

    private void viewPosition(int x, int y) {
        Rectangle bound = cam.getBoundingRectangle();
        Rectangle view = cam.getViewport();
        float px = x - (int) position.x;
        float py = y - (int) position.y;

        px = px - (view.getWidth() / bound.getWidth() * bounds.getWidth()) / 2.0f;
        py = py - (view.getHeight() / bound.getHeight() * bounds.getHeight()) / 2.0f;

        px = px * (bound.getWidth() + view.getWidth() - 2 * 64.0f) / bounds.getWidth();
        py = py * (bound.getHeight() + view.getHeight() - 2 * 64.0f) / bounds.getHeight();
        cam.teleportTo(new Vector2f(px, py));
    }

    @Override
    public void refresh(WorldMap model) {
        this.map = model;

        if ((mapW != map.getWidth()) || (mapH != map.getHeight())) {
            // Rebuild map
            mapW = map.getWidth();
            mapH = map.getHeight();

            // Draw the map
            Graphics g = null;
            try {
                mini = new Image(mapW, mapH);
                g = mini.getGraphics();
            } catch (SlickException sEx) {
                mini = null;
                return;
            }

            g.setColor(Color.lightGray);
            g.fillRect(0, 0, mapW, mapH);
            for (int y = 0; y < map.getHeight(); y++) {
                for (int x = 0; x < map.getWidth(); x++) {
                    Location loc = map.getLocation(x, y);

                    if (loc == null) {
                        g.setColor(Color.black);
                    } else {
                        g.setColor(TileFactory.getInstance().getTile(loc.getName()).getColor());
                    }

                    g.drawLine(x, y, x, y);
                }
            }
            g.flush();
            Image img = mini.getScaledCopy((int) bounds.getWidth(),
                    (int) bounds.getHeight());
            mini = img;
        }
    }

    @Override
    public void render(GameContainer gc, StateBasedGame sbg, Graphics grphcs) throws SlickException {
        if (mini != null) {
            grphcs.setClip(bounds);
            grphcs.drawImage(mini, position.x, position.y);

            if (cam != null) {
                Rectangle bound = cam.getBoundingRectangle();
                Rectangle view = cam.getViewport();
                Rectangle display = new Rectangle(
                        position.x + cam.getPosition().x / (float) (bound.getWidth() + view.getWidth() - 2 * 64) * bounds.getWidth(),
                        position.y + cam.getPosition().y / (float) (bound.getHeight() + view.getHeight() - 2 * 64) * bounds.getHeight(),
                        view.getWidth() / (float) (bound.getWidth() + view.getWidth() - 2 * 64) * bounds.getWidth(),
                        view.getHeight() / (float) (bound.getHeight() + view.getWidth() - 2 * 64) * bounds.getHeight());
                grphcs.setColor(Color.white);
                grphcs.draw(display);
            }
            grphcs.setClip(null);
        }
    }

    @Override
    public void update(GameContainer gc, StateBasedGame sbg, int delta) {}

    @Override
    public void onDeselect() {
    }

    @Override
    public void onSelect() {
    }
}
